<template>
<div style="height: calc(100vh - 223px);">
  <div class="material-header">
    <!-- <span class="material-title">图片素材库</span> -->
	<div>
		<el-input
		    v-model="keywords"
		    style="width: 18.75rem"
		    placeholder="请输入素材名称回车查询"
		    :suffix-icon="Search"
			@keydown.enter="handleSearch"
		/>
	</div>
    <ElButton type="primary" @click="showDialog('add')" :loading="loading">新增素材</ElButton>
  </div>
  <el-scrollbar
    style="height: calc(100vh - 337px);padding: 24px 12px 0 12px;"
    :infinite-scroll-disabled="loading || noMore"
    :infinite-scroll-distance="100"
  >
    <div v-if="tableData.length === 0" class="empty-state">
      <i class="el-icon-picture-outline"></i>
      <p>暂无图片素材，请点击“新增素材”上传</p>
    </div>
    <div v-else class="image-list-grid">
      <div v-for="(img, idx) in tableData" :key="img.id" class="image-list-item" @mouseenter="img.hover=true" @mouseleave="img.hover=false">
        <div class="img-box">
          <img :src="getImageSrc(img)" :alt="img.name || ''" @click="openImageViewer(idx)" />
        </div>
        <div class="image-title">{{ img.name || img.label || '未命名素材' }}</div>
        <div class="image-meta">
          <span v-if="img.width && img.height">{{ img.width }} × {{ img.height }} px</span>
          <span v-if="img.description" class="desc">{{ img.description }}</span>
        </div>
        <transition name="fade">
          <div class="image-actions" v-if="img.hover">
            <el-button size="small" :icon="Edit" @click.stop="showDialog('edit', img)">编辑</el-button>
            <el-button size="small" type="danger" :icon="Delete" @click.stop="handleDelete(img)">删除</el-button>
          </div>
        </transition>
      </div>
    </div>
    <div v-if="loading" class="loading-more">加载中...</div>
    <div v-if="noMore && tableData.length > 0" class="no-more">没有更多了</div>
  </el-scrollbar>
  
  
  
  <!-- element-plus 图片预览 -->
  <el-image-viewer
    v-if="imageViewer.visible"
    :url-list="imageViewer.urlList"
    :initial-index="imageViewer.index"
    @close="imageViewer.visible = false"
  />
  
    <div style="padding-right: 8px;padding-top:5px;display: flex;justify-content: flex-end;align-items: center;border-top: 1px solid var(--art-card-border);">
      <el-pagination
        v-model:current-page="pagination.currentPage"
        v-model:page-size="pagination.pageSize"
        :page-sizes="[20, 50, 100, 200]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagination.total"
		:background="true"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

  <ElDialog
      v-model="dialogVisible"
      :title="dialogType === 'add' ? '添加素材图片' : '编辑素材图片'"
      width="50%"
      align-center
		  :close-on-click-modal="false"
		  draggable
      >

		<ElForm ref="formRef" :model="formData" :rules="rules" label-width="120px">
			<ElFormItem label="缩略图" prop="thumbnail">
				<div class="avatar-upload-wrapper">
					<ElUpload
						class="avatar-uploader"
						ref="upload"
						:auto-upload="false"
						:show-file-list="false"
						:on-change="handleChange"
						:before-upload="beforeUpload"
						accept="image/*"
					>
						<div v-if="imageUrl" class="avatar-img-box" @mouseenter="hovering=true" @mouseleave="hovering=false">
							<img
								:src="imageUrl"
								class="avatar"
								width="120"
								height="120"
								@click="handlePreview"
							>
							<el-button
								v-if="hovering"
								class="avatar-remove-btn"
								type="danger"
								size="small"
								@click.stop="removeImage"
							>移除</el-button>
						</div>
						<div v-else class="avatar-upload-placeholder">
							<el-icon class="avatar-uploader-icon"><Plus /></el-icon>
							<div class="avatar-upload-text">上传图片</div>
						</div>
					</ElUpload>
				</div>
			</ElFormItem>
			<ElFormItem label="图片名称" prop="name">
				<ElInput v-model="formData.name" />
			</ElFormItem>
			<ElFormItem label="图片描述" prop="description">
				<ElInput v-model="formData.description" type="textarea" :rows="3" />
			</ElFormItem>
			<ElFormItem label="宽度(px)" prop="width">
				<ElInput v-model="formData.width" type="number" min="0" placeholder="自动获取或手动填写" />
			</ElFormItem>
			<ElFormItem label="高度(px)" prop="height">
				<ElInput v-model="formData.height" type="number" min="0" placeholder="自动获取或手动填写" />
			</ElFormItem>
      </ElForm>
      <template #footer>
        <div class="dialog-footer">
          <ElButton @click="dialogVisible = false">取消</ElButton>
          <ElButton type="primary" @click="handleSubmit">提交</ElButton>
        </div>
      </template>
    </ElDialog>
</div>
</template>

<script setup lang="ts">
import {
  Delete,
  Edit,
  Search
} from '@element-plus/icons-vue'

import { h, ref, reactive, onMounted, nextTick, computed, watch } from 'vue'
import { ElDialog, ElButton, ElImageViewer, ElScrollbar } from 'element-plus'
import InfiniteScroll from 'element-plus/es/components/infinite-scroll'
import { ElMessageBox, ElMessage } from 'element-plus'
import notFoundImg from '@/assets/img/state/404.png'
import { MaterialService } from '@/api/visual/materialApi'
import { axiosInstance } from '@/utils/http/index'
const data=ref<any>();
const props=defineProps({
  data: {
    type: Object,
    default: () => {}
  },
})

const BASE_API = axiosInstance.defaults.baseURL

// 分页设置
const pagination = reactive({
  currentPage: 1,
  pageSize: 20,
  total: 0
})

const loading = ref(false)
const noMore = ref(false)
const tableData = ref<any[]>([])

// 图片预览 viewer
const imageViewer = reactive({
  visible: false,
  urlList: [] as string[],
  index: 0
})
function openImageViewer(idx: number) {
  imageViewer.urlList = tableData.value.map(getImageSrc)
  imageViewer.index = idx
  imageViewer.visible = true
}

// 图片src统一处理
function getImageSrc(img: any) {
  if (img.url) return `${BASE_API}/visual/material/image/${img.url}`
  return notFoundImg
}

const keywords=ref<string>('');

// 处理表格分页变化
const handleSizeChange = (newPageSize: number) => {
	pagination.pageSize = newPageSize
	fetchData()
}

const handleCurrentChange = (newCurrentPage: number) => {
	pagination.currentPage = newCurrentPage
	fetchData()
}

const handleSearch=()=>{
	pagination.currentPage = 1
	fetchData();
}

const fetchData = async () => {
	loading.value = true
	try{
		const { list, pageNumber, pageSize, totalRow }= await MaterialService.imagePages({
			categoryId:props.data.id,
			keywords:keywords.value,
			pageNumber:pagination.currentPage,
			pageSize:pagination.pageSize,
		})
		tableData.value = list;
		Object.assign(pagination, { 
			currentPage: pageNumber,
			pageSize: pageSize, 
			total:totalRow,
		})
	}catch(error){
		console.error(error);
	}finally{
		loading.value = false
	}
}


onMounted(() => {
  tableData.value = []
  pagination.currentPage = 1
  fetchData();
})

// 新增/编辑弹窗相关响应式变量
const dialogVisible = ref(false)
const dialogType = ref('add') // 'add' or 'edit'
const formRef = ref()
const formData = reactive({
  id: '',
  name: '',
  categoryId: '',
  description: '',
  width: '',
  height: '',
  thumbnailFile: null,
})
const rules = reactive({
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }]
})


// 图片上传相关
const imageUrl = ref('')
const hovering = ref(false)
function handleChange(file: any) {

  formData.thumbnailFile= file.raw;
  // 预览图片
  if (!formData.name) {
    const fileName = file.raw.name || ''
    formData.name = fileName.replace(/\.[^.]+$/, '')
  }
  const reader = new FileReader()
  reader.onload = (e: ProgressEvent<FileReader>) => {
    const result = e.target?.result as string || ''
    imageUrl.value = result
    // 自动获取图片尺寸
    const img = new window.Image()
    img.onload = () => {
      formData.width = img.width.toString()
      formData.height = img.height.toString()
    }
    img.src = result
  }
  reader.readAsDataURL(file.raw)
  
}
function beforeUpload(_file: File) {
  return true
}

function handlePreview() {
  // 预览大图
  // dialogPreviewVisible.value = true // This line is no longer needed
  // previewImgUrl.value = imageUrl.value // This line is no longer needed
}

function removeImage() {
  imageUrl.value = ''
  formData.thumbnailFile = null
}

function showDialog(type = 'add', row: any = null) {
  dialogType.value = type
  dialogVisible.value = true
  if (type === 'edit' && row) {
    Object.assign(formData, row)
    imageUrl.value = row.thumbnail || ''
  } else {
    Object.assign(formData, { id: '', name: '', categoryId: data.value.id, description: '', width: '', height: '', thumbnailFile: null })
    imageUrl.value = ''
  }
}

function handleSubmit() {
  formRef.value.validate(async (valid: boolean) => {
    if (!valid) return
    try {
      const fd = new FormData()
      fd.append('id', formData.id)
      fd.append('name', formData.name)
      fd.append('categoryId', formData.categoryId)
      fd.append('width', formData.width)
      fd.append('height', formData.height)
      fd.append('description', formData.description)
      if (formData.thumbnailFile) {
        fd.append('thumbnailFile', formData.thumbnailFile)
      }
      await MaterialService.saveImage(fd)
      ElMessage.success(dialogType.value === 'add' ? '添加成功' : '编辑成功')
      dialogVisible.value = false
      fetchData()
    } catch (e) {
      ElMessage.error('保存失败')
    }
  })
}

async function handleDelete(img: any) {
  ElMessageBox.confirm('确定要删除该图片素材吗？', '提示', {
    type: 'warning',
    confirmButtonText: '删除',
    cancelButtonText: '取消',
  }).then(async () => {
    try {
      await MaterialService.deleteImage(img.id)
      ElMessage.success('删除成功')
      fetchData()
    } catch (e) {
      ElMessage.error('删除失败')
    }
  })
}


watch(props,() => {
  		data.value=props.data
		fetchData();
  	},
    { immediate: true, deep: true }
  )

</script>

<style scoped>
.material-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px 0 0;
  height: 46px;
  border-radius: 8px 8px 0 0;
  margin-bottom: 0px;
  border-bottom: 1px solid var(--art-card-border);
}
.material-title {
  font-size: 20px;
  font-weight: bold;
  color: #fff;
  letter-spacing: 1px;
  padding-left: 16px;
}
.image-list-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 28px;
  padding: 24px 12px 0 12px;
}

.image-list-item {
  /* background: rgba(36, 44, 66, 0.85); */
  border-radius: 8px;
  box-shadow: 0 4px 32px #1e90ff33, 0 1.5px 0.5px #fff1 inset;
  backdrop-filter: blur(6px);
  border: 1px solid var(--art-card-border) ;
  transition: box-shadow 0.3s, transform 0.3s;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  padding: 8px;
}
.image-list-item:hover {
  box-shadow: 0 12px 48px #409eff99, 0 2px 8px #fff2 inset;
  transform: translateY(-8px) scale(1);
  z-index: 3;
}

.img-box {
  width: 100%;
  height: 160px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 18px 18px 0 0;
  position: relative;
}
.img-box img {
	max-width: 100%;      /* 宽度填满容器 */
	height: 100%;     /* 高度填满容器 */
	object-fit: scale-down; /* 保持比例，裁剪多余部分 */
  
}
.image-list-item:hover .img-box img {
  transform: scale(1.08) rotate(-1deg);
  opacity: 1;
}

.image-title {
  font-size: 17px;
  color:var(--art-gray-600);
  font-weight: 700;
  text-align: center;
  margin: 10px 0 2px 0;
  letter-spacing: 1px;
  text-shadow: 0 2px 8px #0005;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-left: 8px;
  padding-right: 8px;
}

.image-meta {
  font-size: 13px;
  color: #bfc6d1;
  text-align: center;
  margin-bottom: 8px;
  line-height: 1.7;
  background: none;
  border-radius: 0 0 12px 12px;
}

.image-actions {
  position: absolute;
  top: 16px;
  right: 16px;
  display: flex;
  gap: 12px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s;
}
.image-list-item:hover .image-actions {
  opacity: 1;
  pointer-events: auto;
}
.image-actions .el-button {
  border-radius: 20px;
  background: rgba(30,144,255,0.6);
  box-shadow: 0 2px 8px #1e90ff33;
  color: #fff;
  border: none;
  font-weight: 600;
  transition: background 0.2s;
}
.image-actions .el-button:hover {
  background: #409eff;
  color: #fff;
}

.empty-state {
  border-radius: 8px;
  color:var(--art-gray-600);
  font-size: 18px;
  /* margin: 48px 0 0 0; */
  min-height: 340px;
  /* box-shadow: 0 2px 16px #1e90ff22; */
  display: flex;
  justify-content: center;
  align-items: center;
}


.empty-state i {
  font-size: 60px;
  margin-bottom: 16px;
  color: #409eff;
  opacity: 0.4;
}
@media (max-width: 900px) {
  .image-list-grid {
    gap: 10px;
  }
  .image-list-item {
    width: 48vw;
    min-width: 160px;
  }
}
@media (max-width: 600px) {
  .image-list-item {
    width: 98vw;
    min-width: 120px;
  }
}
.loading-more {
  text-align: center;
  color: #8fa1c7;
  font-size: 15px;
  margin: 16px 0;
}
.no-more {
  text-align: center;
  color: #bfc6d1;
  font-size: 14px;
  margin: 12px 0 0 0;
}
.el-scrollbar__bar {
  background: #1e90ff33 !important;
  border-radius: 8px;
}
.avatar-upload-wrapper {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  min-height: 140px;
}

.avatar-uploader {
  width: 130px;
  height: 130px;
  border-radius: 12px;
  /* background: linear-gradient(135deg, #232a3a 60%, #1e90ff22 100%); */
  box-shadow: 0 2px 16px #1e90ff22;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: box-shadow 0.3s, border 0.3s;
  border: 2px dashed #409eff88;
  overflow: hidden;
}
.avatar-uploader:hover {
  box-shadow: 0 6px 32px #409eff55;
  border: 2px solid #409eff;
}

.avatar-upload-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #8fa1c7;
  font-size: 16px;
  background: transparent;
  transition: background 0.2s;
}
.avatar-uploader-icon {
  font-size: 48px !important;
  color: #409effcc;
  margin-bottom: 8px;
  transition: color 0.2s;
}
.avatar-upload-text {
  font-size: 15px;
  color: #bfc6d1;
  letter-spacing: 1px;
}

.avatar-img-box {
  width: 100%;
  height: 100%;
  border-radius: 0px;
  overflow: hidden;
  position: relative;
  /* box-shadow: 0 2px 16px #409eff33;
  background: #181c24; */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
}
.avatar-img-box img.avatar {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* border-radius: 12px;
  transition: transform 0.3s, box-shadow 0.3s;
  box-shadow: 0 2px 12px #1e90ff22; */
}
.avatar-img-box:hover img.avatar {
  /* transform: scale(1.06); */
  box-shadow: 0 6px 24px #409eff55;
}

.avatar-remove-btn {
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%) scale(0.95);
  opacity: 0;
  transition: opacity 0.2s, transform 0.2s;
  z-index: 2;
  padding: 2px 18px;
  font-size: 14px;
  border-radius: 16px;
  background: rgba(255, 0, 0, 0.8);
  border: none;
}
.avatar-img-box:hover .avatar-remove-btn {
  opacity: 1;
  transform: translateX(-50%) scale(1.08);
}
</style>